#! /usr/bin/perl

#also enable strict mode
use strict;

#use the HMTLSubs package and ValidationSubs package
use HTMLSubs;
use ValidationSubs;
use DBQueries;
use CGI;

#start by obtaining the input so that the username can be determined
my $input = obtain_input();

#ensure that input is not blank which would mean that the site is illegally accessed
if(length($input) == 0){
	
	#if so, redirect to login
	print CGI -> redirect("login.pl.cgi");
}

#call method to split the full string into a hash of individual variables
#this subroutine returns a reference to the submitted info hash
my $ref_user_info = HTMLSubs->decode_input($input);

#dereference the submitted info
my %user_info = %$ref_user_info;

#declare variable to hold username
my $username;

#if the only input is username i.e. the size is 1, 
if(scalar(keys %user_info) == 1){
	
	#isolate username
	$username = $user_info{'username'};
	
	#this method will return an array with all the information
	my ($first_name, $last_name, $email) = DBQueries::getUserInfo($username);
	
	#store relevant information in the hash of correct values necessary for this page
	my %correct_entries = (
			firstName => $first_name,
			lastName => $last_name,
			email => $email,
	);
	
	#now call the subroutine to display the update form
	display_update("", \%correct_entries);
}

#otherwise we know that further information was submitted to the script so we verify if the user made valid changes
else{
	
	#now call subroutine to process input
	#pass this sub the reference to submitted info
	#this subroutine will take control of the flow of the script and determine what actions to further take
	process_update();
}

#subroutine to both determine the validity of the users input and to process all data
#this subroutine will call a subroutine to determine if each of the data fields was entered correctly
#each of those decisions will be stored in a "boolean" variable so the script can then notify the user of all errors individually
sub process_update{
	
	$username = $user_info{'username'};
	
	#declare boolean variables
	my ($validFName, $validLName, $validEmail);
	
	#call subroutines to determine each validtiy
	$validFName = ValidationSubs->validate_name($user_info{'firstName'});
	$validLName = ValidationSubs->validate_name($user_info{'lastName'});
	$validEmail = ValidationSubs->validate_email($user_info{'email'});
	
	#now ensure that all information was correct
	if($validFName == 1 && $validLName == 1 && $validEmail == 1){
		
		#call subroutine to add information to database
		DBQueries::updateUserInfo($username, $user_info{'firstName'}, $user_info{'lastName'}, $user_info{'email'});
		
		#call subroutine to show success screen (this screen will take the user to the main menu)
		show_success();
	}
	#otherwise show submission screen again with proper error messages
	else{
		
		#declare hash to store individual error messages associated with individual incorrect inpus
		my %errors;
		
		#declare hash to store any potential valid inputs to ease re-submission
		my %correct;
		
		#now go through each submission and add error messages or correct values
		#first name
		if($validFName == 1){
			
			#add value to correct and blank to error
			$correct{'firstName'} = $user_info{'firstName'};
			$errors{'firstName'} = "";
		}
		else{
			
			#add blank to correct and message to error
			$correct{'firstName'} = "";
			$errors{'firstName'} = "<tr><td></td><td><font color=\"red\" size=\"2\">Invalid First Name Given</font></td></tr>";
		}
		
		#last name
		if($validLName == 1){
			
			#add value to correct and blank to error
			$correct{'lastName'} = $user_info{'lastName'};
			$errors{'lastName'} = "";
		}
		else{
			
			#add blank to correct and message to error
			$correct{'lastName'} = "";
			$errors{'lastName'} = "<tr><td></td><td><font color=\"red\" size=\"2\">Invalid Last Name Given</font></td></tr>";
		}
		
		#email
		if($validEmail == 1){
			
			#add value to correct and blank to error
			$correct{'email'} = $user_info{'email'};
			$errors{'email'} = "";
		}
		else{
			
			#add blank to correct and message to error
			$correct{'email'} = "";
			$errors{'email'} = "<tr><td></td><td><font color=\"red\" size=\"2\">Invalid Email Given</font></td></tr>";
		}
		
		#now that the individual errors were determined, call the subroutine to re-display the form and pass it the proper values and error messages
		#declare error message
		my $main_error_message = "<h4><font color=\"red\">Your profile was not updated because some information was incorrectly entered. <br>Please see the individual fields for details and try again.</font></h4>";
		display_update($main_error_message, \%correct, \%errors);
	}
}

#subroutine that is called whenever the user succesfully submits his/her data
#this subroutine will display a success message to the user before redirecting to the main window
sub show_success{
	
	#call method to display html beginnign
	HTMLSubs->generate_html_beginning("Successfully Updated Account!");
	
	#call sub to print header
	HTMLSubs -> generate_display_head("Document Management System", "Successfully Updated!", $username);
	
	print <<END_HTML;
	
	<!--now display the message to the user-->
	<h4>You can manage your account further through your profile.</h4>
	<br>
	
END_HTML

	#create hash for button
	my %username_hash;
	$username_hash{'username'} = $username;
	
	#call subroutine to display button that returns the user to the profile
	HTMLSubs -> generate_html_button("profile.pl.cgi", "Go To profile", \%username_hash);

	#now call method to produce closing html tags
	HTMLSubs->generate_html_end();
}

#subroutine to display the update page
#this subroutine takes three potential parameters, one which is an error message or any text to be displayed above the form
#and the other is an array of error messages associated with individual fields
#and the last one is a hash of previously entered correct values
sub display_update{
	
	#obtain potential messages
	my $error_text = $_[0];
	
	#obtain potential correct entries to re-display in form
	my $ref_correct_entries = $_[1] || "";
	
	#obtain errors
	my $ref_individual_errors = $_[2] || "";
	
	#call routine to display beginning of html
	HTMLSubs -> generate_html_beginning("Update User Information");
	
	#call the subroutine to create the html code for the actual form and pass it the correct entries reference
	generate_update_html($ENV{'SCRIPT_NAME'}, $ref_correct_entries, $ref_individual_errors);
	
	#call the subroutine to end the html code
	HTMLSubs -> generate_html_end();
}

#subroutine to create the html update form
#this sub is passed the name of the target for the form
#also, this sub is passed an array of individual error messages associated with possible incorrect previous submissions
sub generate_update_html{
	
	#obtain target
	my $form_target = $_[0];
	
	#obtain potential correct entries to re-display in form
	my $ref_correct_entries = $_[1] || "";
	
	#dereference or create empty hash if no reference exits
	my %correct_entries;
	
	#check if refernce is empty
	if(length($ref_correct_entries) == 0){
		
		#in this case create an empty hash
		%correct_entries = {};
	}
	#otherwise use reference
	else{
		%correct_entries = %$ref_correct_entries;
	}
	
	#obtain errors
	my $ref_individual_errors = $_[2] || "";
	
	#dereference or create empty hash if no reference exits
	my %individual_errors;
	
	#check if refernce is empty
	if(length($ref_individual_errors) == 0){
		
		#in this case create an empty hash
		%individual_errors = {};
	}
	#otherwise use reference
	else{
		%individual_errors = %$ref_individual_errors;
	}
	
	#create a hash containing only the username key/value pair to be passed to the button creation subroutine
	my %username_hash;
	$username_hash{'username'} = $username;
	
	#call sub to print header
	HTMLSubs -> generate_display_head("Document Management System", "Update User", $username);
	
	print <<END_HTML;
	<!--content-->
	<!-- place form in table for appearance formatting-->
	<!-- individual error messages are displayed below the designated fields if those messages are not intentionally left blank-->
		<table>
			<form action="$form_target" method=POST>
			<tr>
				<!-- username-->
				<td><p>Username:*</p></td>
				<td><input disabled type="text" name="hidden_username" value="$username"></td>
			</tr>
			<tr>
				<!-- first name-->
				<td><p>First Name:*</p></td>
				<td><input type="text" name="firstName" value="$correct_entries{'firstName'}"></td>
			</tr>
			$individual_errors{'firstName'}
			<tr>
				<!-- last name-->
				<td><p>Last Name:*</p></td>
				<td><input type="text" name="lastName" value="$correct_entries{'lastName'}"></td>
			</tr>
			$individual_errors{'lastName'}
			<tr>
				<!-- email-->
				<td><p>Email:*</p></td>
				<td><input type="text" name="email" value="$correct_entries{'email'}"></td>
			</tr>
			$individual_errors{'email'}
			
			<!-- now create a hidden field that resubmits the usernmae so that the script knows what user is being passed back-->
			<input type="hidden" name="username" value="$username">
			
			<tr>
				<!-- submit button and cancel button-->
				<td><input type="submit" value="Submit"></form>
END_HTML
				#call subroutine to crate a cancel button
				#this button will link back to the profile
				HTMLSubs -> generate_html_button("profile.pl.cgi", "Cancel", \%username_hash);
			
				#continue printing html
				print <<END_HTML;
			</td>	
			</tr>
			<tr>
				<!--change password button-->
				<td>
END_HTML
				#call subroutine to create a button to link to change password
				HTMLSubs -> generate_html_button("changePassword.pl.cgi", "ChangePassword", \%username_hash);
				
				#print remainder of html tags
				print <<END_HTML;
				</td>
			</tr>
		</table>
END_HTML

}

#subroutine to obtain and determine what information is passed to the script
#to make this more universal, both GET and POST methods are accepted 
#this reads input for both GET and POST
sub obtain_input{

	#declare scalar to hold passed information
	my $input;

	#now retrieve the input through either get or post
	#change the case of request method
	$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;

	#if post use STDIN
	if ($ENV{'REQUEST_METHOD'} eq "POST"){
		read(STDIN, $input, $ENV{'CONTENT_LENGTH'});

		#exchange plus signs to spaces
		$input =~ s/\+/ /;

		#deal with special characters using the substitution sample provided
		$input =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
	}
	#otherwise the env hash
	else{
		$input = $ENV{'QUERY_STRING'};
		
		#exchange plus signs to spaces
		$input =~ s/\+/ /;
		
		#deal with special characters using the substitution sample provided
		$input =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
	}
	
	#now return the correct input
	return $input;	
}